/* server.cpp */
#include "protocol.h"
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
using namespace std;

// 子线程执行函数
void* Routine(void* arg)
{
  pthread_detach(pthread_self());
  int linkSock = *(int*)arg;
  delete (int*)arg;
  // 针对处理某一个客户端发来的任务，直到客户端关闭或接收数据失败，这个线程才结束 
  while(1)
  {
    Request rq;
    ssize_t size = recv(linkSock, &rq, sizeof(rq), 0);
    if(size > 0)
    {
      Respond rp;
      switch(rq.op)
      {
        case '+':
          rp.result = rq.x + rq.y;
          break;
        case '-':
          rp.result = rq.x - rq.y;
          break;
        case '*':
          rp.result = rq.x * rq.y;
          break;
        case '/':
          if(rq.y == 0)
          {
            rp.status = 1;
          }
          else 
          {
            rp.result = rq.x / rq.y;
          }
          break;
        case '%':
          if(rq.y == 0)
          {
            rp.status = 2;
          }
          else 
          {
            rp.result = rq.x % rq.y;
          }
          break;
        default:
          rp.status = 3;
          break;
      }
      send(linkSock, &rp, sizeof(rp), 0);
    }
    else if(size == 0)
    {
      cout<<"client close!"<<endl;
      break;
    }
    else 
    {
      cerr<<"recv error"<<endl;
      break;
    }
  }
  close(linkSock);
  return nullptr;
}

int main(int argc, char* argv[])
{
  // 检查传入的命令行参数是否符合要求
  if(argc != 2)
  {
    cerr<<"Usage：serverName serverPort"<<endl;
    exit(1);
  }
  // 解析传入的命令行参数
  int port = atoi(argv[1]);
  // 创建套接字
  int listenSock = socket(AF_INET, SOCK_STREAM, 0);
  if(listenSock < 0)
  {
    cerr<<"socket error"<<endl;
    exit(2);
  }
  // 绑定socket地址
  struct sockaddr_in local;
  memset(&local, 0, sizeof(local));
  local.sin_family = AF_INET;
  local.sin_port = htons(port);
  local.sin_addr.s_addr = htonl(INADDR_ANY);
  if(bind(listenSock, (struct sockaddr*)&local, sizeof(local)) < 0)
  {
    cerr<<"bind error"<<endl;
    exit(3);
  }
  // 设置监听套接字
  if(listen(listenSock, 5) < 0)
  {
    cerr<<"listen error"<<endl;
    exit(4);
  }
  // 不断地建立连接，然后创建子线程去处理连接任务
  struct sockaddr_in peer;
  memset(&peer, 0, sizeof(peer));
  socklen_t len = sizeof(peer);
  while(1)
  {
    int linkSock = accept(listenSock, (struct sockaddr*)&peer, &len);
    if(linkSock < 0)
    {
      cout<<"accept fail, continue next"<<endl;
      continue;
    }
    else 
    {
      cout<<"get a new link"<<endl;
      int* pLinkSock = new int(linkSock);
      pthread_t pid;
      pthread_create(&pid, nullptr, Routine, pLinkSock);
    }
  }
  
  return 0;
}
